package com.ccteam.fluidmusic.ui.user

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.os.bundleOf
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.setFragmentResult
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import cn.hutool.core.date.DateTime
import com.bumptech.glide.Glide
import com.ccteam.fluidmusic.R
import com.ccteam.fluidmusic.databinding.FragmentSelfInformationBinding
import com.ccteam.fluidmusic.utils.EventObserver
import com.ccteam.fluidmusic.utils.TransitionUtils
import com.ccteam.fluidmusic.view.bean.LoadMessage
import com.ccteam.fluidmusic.widget.SNACKBAR_ALL_BOTTOM_BAR
import com.ccteam.fluidmusic.widget.SNACKBAR_BOTTOM
import com.ccteam.fluidmusic.widget.snackbar
import com.ccteam.shared.result.user.UserInfoEditInfo
import com.google.android.material.datepicker.CalendarConstraints
import com.google.android.material.datepicker.DateValidatorPointBackward
import com.google.android.material.datepicker.MaterialDatePicker
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class SelfInformationFragment : Fragment() {

    private var _binding: FragmentSelfInformationBinding? = null
    private val binding get() = _binding!!

    private val genderItems = arrayOf("男","女","保密")

    private val selfInformationViewModel by viewModels<SelfInformationViewModel>()

    companion object{
        const val RESULT_USER_INFO_KEY = "result_user_info"
    }

    /**
     * 选择图片的内容
     * 选择完手机中的图片后，将其存储到ViewModel中
     */
    private val selectImage = registerForActivityResult(ActivityResultContracts.GetContent()) { imageUri ->
        imageUri?.let {
            selfInformationViewModel.setHeadPhoto(it.toString())
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        exitTransition = TransitionUtils.exitScale
        reenterTransition = TransitionUtils.enterScale
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentSelfInformationBinding.inflate(inflater,container,false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        binding.toolbarEditUserInfo.setNavigationOnClickListener {
            findNavController().navigateUp()
        }

        binding.ivUserPhoto.setOnClickListener {
            selectImage.launch("image/*")
        }

        binding.editUserBirthday.setOnClickListener {
            val builder = setupDateSelectorBuilder()
            val constraintsBuilder = setupConstraintsBuilder()
            builder.setCalendarConstraints(constraintsBuilder)
            // 展示日期选择器
            val picker = builder.build()
            picker.addOnPositiveButtonClickListener {
                binding.editUserBirthday.text = DateTime.of(it).toString("yyyy-MM-dd")
            }
            picker.show(childFragmentManager,picker.toString())
        }

        selfInformationViewModel.editUserInfo.observe(viewLifecycleOwner, {
            updateUserInfo(it)
        })

        selfInformationViewModel.uploadPhotoStatus.observe(viewLifecycleOwner, EventObserver{
            updatePhotoProgress(it is LoadMessage.Loading)
            when (it) {
                is LoadMessage.Success -> {
                    view.snackbar(R.string.description_upload_head_photo_success, SNACKBAR_BOTTOM).show()
                }
                is LoadMessage.Error -> {
                    view.snackbar(it.errorMessage.description.toString(), SNACKBAR_BOTTOM).show()
                }
                else -> {}
            }
        })

        selfInformationViewModel.loadMessage.observe(viewLifecycleOwner, {
            binding.containerEditUserInfo.isVisible = it is LoadMessage.NotLoading
            binding.statusView.changeToErrorStatus(it)
            binding.statusView.changeToLoadingStatus(it is LoadMessage.Loading)
        })

        selfInformationViewModel.editUserInfoLoadMessage.observe(viewLifecycleOwner, EventObserver{
            updateStatus(it is LoadMessage.Loading)
            if(it is LoadMessage.Success){
                view.snackbar(R.string.description_edit_success, SNACKBAR_ALL_BOTTOM_BAR).show()
                setFragmentResult(
                    RESULT_USER_INFO_KEY, bundleOf(
                        RESULT_USER_INFO_KEY to true)
                )
                findNavController().navigateUp()
            } else if(it is LoadMessage.Error){
                view.snackbar(R.string.description_edit_fail, SNACKBAR_BOTTOM).show()
            }
        })

        binding.statusView.setRetryClickListener {
            selfInformationViewModel.refreshUserInfo()
        }

        binding.btnEditUser.setProgressButtonOnClickListener {
            selfInformationViewModel.editUserInfo(
                binding.editUserName.editText?.text.toString(),
                binding.editUserIntroduction.editText?.text.toString(),
                binding.editUserBirthday.text.toString(),
                binding.editUserGender.text.toString()
            )
        }

        binding.editUserGender.setOnClickListener {
            val selectIndex = genderItems.indexOf(binding.editUserGender.text)
            MaterialAlertDialogBuilder(requireContext())
                .setTitle(resources.getString(R.string.hint_edit_user_gender))
                .setNeutralButton(resources.getString(R.string.description_cancel)) { _, _ ->
                }
                .setPositiveButton(resources.getString(R.string.description_confirm)) { _, _ ->
                }
                .setSingleChoiceItems(genderItems, selectIndex) { dialog, which ->
                    binding.editUserGender.text = genderItems[which]
                    dialog.dismiss()
                }
                .show()
        }

    }

    /**
     * 如果图片正在上传，则不允许其点击下方的内容，展示一层蒙版并禁止控件使用
     */
    private fun updatePhotoProgress(isLoading: Boolean) = with(binding){
        containerPhotoProgress.isVisible = isLoading
    }

    private fun updateUserInfo(userInfo: UserInfoEditInfo) = with(binding){
        editUserName.editText?.setText(userInfo.userName)
        editUserIntroduction.editText?.setText(userInfo.userIntroduction)
        if(userInfo.userBirthday.isNotEmpty()){
            editUserBirthday.text = userInfo.userBirthday
        }
        if(userInfo.userBirthday.isNotEmpty()){
            editUserGender.text = userInfo.userGender
        }

        Glide.with(ivUserPhoto)
            .load(userInfo.userImgUrl)
            .placeholder(R.drawable.img_default_artist_small)
            .into(ivUserPhoto)
    }

    /**
     * 当正在提交用信息中，不允许按钮多次点击，并设置按钮为加载状态
     */
    private fun updateStatus(isLoading: Boolean) = with(binding){
        editUserGender.isEnabled = !isLoading
        editUserName.isEnabled = !isLoading
        editUserIntroduction.isEnabled = !isLoading
        editUserBirthday.isEnabled = !isLoading
        btnEditUser.setLoading(isLoading)
    }

    /**
     * 生成日期控件构造器
     */
    private fun setupDateSelectorBuilder(): MaterialDatePicker.Builder<Long>{
        return MaterialDatePicker.Builder.datePicker().apply {
            setInputMode(MaterialDatePicker.INPUT_MODE_CALENDAR)
        }
    }

    /**
     * 创建日期限制器
     * 限制只能选择以前的日期
     */
    private fun setupConstraintsBuilder(): CalendarConstraints{
        val builder = CalendarConstraints.Builder()
        builder.setValidator(DateValidatorPointBackward.now())
        return builder.build()
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}